// MouseMage, a rodent behavioral data collection and analysis program for Android devices.
// Copyright (C) 2012 Joseph Van Swearingen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package com.zythran.mousemage;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.widget.TextView;
import android.text.format.Time;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
//import android.view.View.OnClickListener;

public class MouseMageActivity extends Activity implements View.OnClickListener {
    /** Called when the activity is first created. */
	
	private Button start_btn ;
	private Button pause_btn ;
	private Button prev_btn ;
	private Button next_btn ;
	
	private ToggleButton asleep_btn ;
	private ToggleButton awakestill_btn ;
	
	private ToggleButton loco_int_btn ;
	private ToggleButton loco_cont_btn ;
	private ToggleButton loco_maint_btn ;
	private ToggleButton loco_rand_btn ;
	private ToggleButton loco_patt_btn ;
	private ToggleButton loco_fast_btn ;	
	
	private ToggleButton piv_once_btn ;
	private ToggleButton piv_int_btn ;
	private ToggleButton piv_cont_btn ;
	private ToggleButton piv_maint_btn ;
	
	private ToggleButton groom_int_btn ;
	private ToggleButton groom_cont_btn ;
	private ToggleButton groom_maint_btn ;
	private ToggleButton groom_intense_btn ;
	
	private ToggleButton rear_int_btn ;
	private ToggleButton rear_cont_btn ;
	private ToggleButton rear_maint_btn ;
	
	private ToggleButton dysk_limb_btn ;
	private ToggleButton dysk_injury_btn ;
	private ToggleButton dysk_seizures_btn ;
	private ToggleButton dysk_laying_side_btn ;

	private ToggleButton sniff_once_btn ;
	private ToggleButton sniff_int_btn ;
	private ToggleButton sniff_cont_btn ;
	private ToggleButton sniff_maint_btn ;
	private ToggleButton sniff_hup_btn ;
	private ToggleButton sniff_hdn_btn ;
	private ToggleButton sniff_fix_btn ;
	private ToggleButton sniff_intense_btn ;
	
	private ToggleButton other_head_btn ;
	private ToggleButton other_twitch_btn ;
	private ToggleButton other_bed_btn ;
	private ToggleButton other_flatpos_btn ;
	private ToggleButton other_licking_btn ;
	private ToggleButton other_mouth_movement_btn ;
	private ToggleButton other_erect_tail_btn ;

    private EditText other_dysk_txt ;
    private EditText novel_beh_txt ;
    
	private MouseModel mm ;
	
	private SharedPreferences settings ;
	
	private int timepoint ;
	private int animal ;
	private int bin ;
	private int protocol ;
	private String start_notes_txt ;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //Bundle extras = getIntent().getExtras();
        //boolean recreate = !extras.getBoolean("starting") ;
        //boolean reload_from_file = extras.getBoolean("reload_from_file") ;
        
        String reload_bfr = "";
        
        TextView bottom_text = (TextView) findViewById( R.id.label_bottom ) ;
        settings = getSharedPreferences("MouseMagePrefs", MODE_PRIVATE );  
        
        boolean recreate = settings.getBoolean("started", false) ;
        boolean reload_from_file = settings.getBoolean("reload_from_file", false) ;
        
        SharedPreferences.Editor ed = settings.edit() ;
        ed.putBoolean("started", true) ;
        ed.commit() ;
        
        if (reload_from_file) {
        	String filebfr = open_restore_file() ;
        	Log.i("restore", filebfr) ;
        	String tokens[] = filebfr.split("//!") ;
        	Log.i("restore", tokens[0]) ;
        	Log.i("restore", tokens[1]) ;
        	Log.i("restore", tokens[2]) ;
        	Log.i("restore", tokens[3]) ;
        	timepoint = Integer.parseInt(tokens[0]) ;
        	animal = Integer.parseInt(tokens[1]) ;
        	bin = Integer.parseInt(tokens[2]) ;
        	protocol = Integer.parseInt(tokens[3]) ;
        	reload_bfr = tokens[4] ;
        	Log.i("restore", "restoring from a backup file") ;
        	Log.i("restore", reload_bfr) ;
        } else if (recreate) {
        	timepoint   = settings.getInt("num_timepoints", 1);
        	animal   = settings.getInt("num_animals", 1);
        	bin = settings.getInt("num_bins", 1);
        	protocol = settings.getInt("protocol", 1) ;
        	start_notes_txt = settings.getString("start_notes_txt", "") ;
        	Log.i("recreate", "recreating an existing state") ;
        } else {
        	// starting fresh
        	timepoint = settings.getInt("num_timepoints", 1) ;
        	animal = settings.getInt("num_animals", 1) ;
        	bin = settings.getInt("num_bins", 1) ;
        	protocol = settings.getInt("protocol", 1) ;
        	start_notes_txt = settings.getString("start_notes_txt", "") ;
        	Log.i("new", "not recreating") ;
        }
       	
        mm = new MouseModel(timepoint, animal, bin) ;

        if (reload_from_file) {
        	//ed.putBoolean("reload_from_file", false) ;
        	//ed.commit() ;
        	String tokens[] = reload_bfr.split("//@") ;
        	int cur = 0 ;
        	String cur_pos_str = tokens[0] ;
        	Log.i("CPSTR", cur_pos_str) ;
        	String done_str = tokens[1] ;
        	Log.i("DSTR", done_str) ;
        	start_notes_txt = tokens[2] ;
        	Log.i("SNT", start_notes_txt) ;
        	start_notes_txt = start_notes_txt.substring(1) ;
        	int cur_pos = Integer.parseInt(cur_pos_str) ;
        	int done_i = Integer.parseInt(done_str) ;
        	boolean done_b = (done_i == 1) ? true : false ;
        	int idx ;
        	for (idx=3; idx < tokens.length; idx++) {
        		String line = tokens[idx] ;
        		mm.mouse_iteration[cur].setState(line) ;
        		cur++ ;
        	}
        	mm.cur = cur_pos ;
        	mm.done = done_b ;
        	//Toast.makeText(getApplicationContext(), "Reloading from file at pos "+cur_pos, Toast.LENGTH_LONG).show() ;
        	if (cur_pos != 0) {
        		mm.at_start = false ;
        	}
        } else if (recreate) {
        	int cur ;
        	for (cur = 0; cur < mm.num_elems; cur++) {
        		String state = settings.getString("state"+cur, "") ;
        		Log.i("state", "Trying state for elem "+cur) ;
        		if (state != "") {
        			bottom_text.setText("Welcome back") ;
        		}
        		mm.mouse_iteration[cur].setState(state) ;
        	}
        	mm.cur = settings.getInt("cur", 0) ;
        	mm.at_start = (mm.cur == 0) ;
        	mm.done = settings.getBoolean("done", false) ;
        	//Toast.makeText(getApplicationContext(), "Recreating context at pos "+mm.cur+" At start="+mm.at_start, Toast.LENGTH_LONG).show() ;
        	
        } else {
        	//Toast.makeText(getApplicationContext(), "Starting context at 0", Toast.LENGTH_LONG).show() ;
        	
        }
        
    	start_btn = (Button) findViewById(R.id.start_btn);
    	pause_btn = (Button) findViewById(R.id.pause_btn);
    	prev_btn  = (Button) findViewById(R.id.prev_btn);
    	next_btn  = (Button) findViewById(R.id.next_btn);
    	
    	asleep_btn      = (ToggleButton) findViewById(R.id.asleep_btn);
    	awakestill_btn  = (ToggleButton) findViewById(R.id.awakestill_btn);
    	
    	loco_int_btn    = (ToggleButton) findViewById(R.id.loco_int_btn);
    	loco_cont_btn   = (ToggleButton) findViewById(R.id.loco_cont_btn);
    	loco_maint_btn  = (ToggleButton) findViewById(R.id.loco_maint_btn);
    	loco_rand_btn   = (ToggleButton) findViewById(R.id.loco_rand_btn);
    	loco_patt_btn   = (ToggleButton) findViewById(R.id.loco_patt_btn);
    	
    	piv_once_btn   = (ToggleButton) findViewById(R.id.piv_once_btn);
    	piv_int_btn    = (ToggleButton) findViewById(R.id.piv_int_btn);
    	piv_cont_btn   = (ToggleButton) findViewById(R.id.piv_cont_btn);
    	piv_maint_btn  = (ToggleButton) findViewById(R.id.piv_maint_btn);
    	
    	groom_int_btn    = (ToggleButton) findViewById(R.id.groom_int_btn);
    	groom_cont_btn   = (ToggleButton) findViewById(R.id.groom_cont_btn);
    	groom_maint_btn  = (ToggleButton) findViewById(R.id.groom_maint_btn);
    	
    	rear_int_btn    = (ToggleButton) findViewById(R.id.rear_int_btn);
    	rear_cont_btn   = (ToggleButton) findViewById(R.id.rear_cont_btn);
    	rear_maint_btn  = (ToggleButton) findViewById(R.id.rear_maint_btn);
    	
    	dysk_limb_btn    = (ToggleButton) findViewById(R.id.dy_limb_btn);
        dysk_injury_btn  = (ToggleButton) findViewById(R.id.dy_hurt_btn);

    	sniff_once_btn   = (ToggleButton) findViewById(R.id.sniff_once_btn);
    	sniff_int_btn    = (ToggleButton) findViewById(R.id.sniff_int_btn);
    	sniff_cont_btn   = (ToggleButton) findViewById(R.id.sniff_cont_btn);
    	sniff_maint_btn  = (ToggleButton) findViewById(R.id.sniff_maint_btn);
    	sniff_hup_btn    = (ToggleButton) findViewById(R.id.sniff_hup_btn);
    	sniff_hdn_btn    = (ToggleButton) findViewById(R.id.sniff_hdn_btn);
    	sniff_fix_btn    = (ToggleButton) findViewById(R.id.sniff_fix_btn);
    	
    	other_head_btn    = (ToggleButton) findViewById(R.id.other_head_btn);
    	other_twitch_btn  = (ToggleButton) findViewById(R.id.other_twitch_btn);
    	other_bed_btn     = (ToggleButton) findViewById(R.id.other_bed_btn);
    	other_flatpos_btn = (ToggleButton) findViewById(R.id.other_flatpos_btn);
    	other_licking_btn = (ToggleButton) findViewById(R.id.other_licking_btn);
    	other_dysk_txt    = (EditText) findViewById(R.id.other_dysk_fillin) ;
    	novel_beh_txt     = (EditText) findViewById(R.id.novel_behavior_fillin) ;
    	
    	loco_fast_btn        = (ToggleButton) findViewById(R.id.loco_fast_btn) ;
    	groom_intense_btn    = (ToggleButton) findViewById(R.id.groom_intense_btn) ;
    	sniff_intense_btn    = (ToggleButton) findViewById(R.id.sniff_intense_btn) ;
    	dysk_seizures_btn    = (ToggleButton) findViewById(R.id.dy_seizures_btn) ;
    	dysk_laying_side_btn = (ToggleButton) findViewById(R.id.dy_laying_side_btn) ;
    	other_mouth_movement_btn = (ToggleButton) findViewById(R.id.other_mouthmov_btn) ;
    	other_erect_tail_btn = (ToggleButton) findViewById(R.id.other_erect_tail_btn) ;

    	  // Control buttons
    	
        start_btn.setOnClickListener(this) ;
        pause_btn.setOnClickListener(this) ;
        prev_btn.setOnClickListener(this) ;
        next_btn.setOnClickListener(this) ;
        
          // Low activity buttons

        asleep_btn.setOnClickListener(this) ;
        awakestill_btn.setOnClickListener(this) ;
        
          // Locomotion buttons

        loco_int_btn.setOnClickListener(this) ;
        loco_cont_btn.setOnClickListener(this) ;
        loco_maint_btn.setOnClickListener(this) ;
        loco_rand_btn.setOnClickListener(this) ;
        loco_patt_btn.setOnClickListener(this) ;
        
          // Pivoting buttons
        
        piv_once_btn.setOnClickListener(this) ;
        piv_int_btn.setOnClickListener(this) ;
        piv_cont_btn.setOnClickListener(this) ;
        piv_maint_btn.setOnClickListener(this) ;
        
          // Grooming buttons
        
        groom_int_btn.setOnClickListener(this) ;        
        groom_cont_btn.setOnClickListener(this) ;
        groom_maint_btn.setOnClickListener(this) ;
        
          // Rearing buttons
        
        rear_int_btn.setOnClickListener(this) ;
        rear_cont_btn.setOnClickListener(this) ;
        rear_maint_btn.setOnClickListener(this) ;
        
    	dysk_limb_btn.setOnClickListener(this) ;
    	dysk_injury_btn.setOnClickListener(this) ;
        		
          // Sniffing buttons
        
        sniff_once_btn.setOnClickListener(this) ;
        sniff_int_btn.setOnClickListener(this) ;
        sniff_cont_btn.setOnClickListener(this) ;
        sniff_maint_btn.setOnClickListener(this) ;
        sniff_hup_btn.setOnClickListener(this) ;
        sniff_hdn_btn.setOnClickListener(this) ;
        sniff_fix_btn.setOnClickListener(this) ;
        
          // Misc. buttons

        other_head_btn.setOnClickListener(this) ;
        other_twitch_btn.setOnClickListener(this) ;
        other_bed_btn.setOnClickListener(this) ;
        other_flatpos_btn.setOnClickListener(this) ;
        other_licking_btn.setOnClickListener(this) ;
        
    	loco_fast_btn.setOnClickListener(this) ;
    	groom_intense_btn.setOnClickListener(this) ;
    	sniff_intense_btn.setOnClickListener(this) ;
    	dysk_seizures_btn.setOnClickListener(this) ;
    	dysk_laying_side_btn.setOnClickListener(this) ;
    	other_mouth_movement_btn.setOnClickListener(this) ;
    	other_erect_tail_btn.setOnClickListener(this) ;
    	
       	if (mm.cur == 0) {
       		prev_btn.setText("(Prev)") ;
       	}
       	
       	if (mm.cur == (mm.num_elems - 1)) {
       		next_btn.setText("Finish") ;
       	}
       	
       	if (recreate || reload_from_file) {
       		reload_button_states() ;
       	}
        
        MouseIteration mcur = mm.curIteration();
        
        TextView time_text = (TextView) findViewById( R.id.timepoint_lbl ) ;
        TextView animal_text = (TextView) findViewById( R.id.animal_lbl ) ; 
        TextView bin_text = (TextView) findViewById( R.id.bin_lbl ) ;
        
    	time_text.setText("Timepoint: " + mcur.timepoint) ;
    	animal_text.setText("Animal: " + mcur.animal) ; 
    	bin_text.setText("Bin: " + mcur.bin) ;
    }
    
    @Override
    public void onPause() {
    	super.onPause() ;
    	SharedPreferences.Editor ed = settings.edit() ;
    	
    	ed.putInt("timepoint", mm.num_timepoints) ;
    	ed.putInt("animal", mm.num_animals) ;
    	ed.putInt("bin", mm.num_bins) ;
    	ed.putInt("protocol", protocol) ;
    	
        // Regardless of what was pressed, save the text fields to their proper owner
        other_dysk_txt = (EditText) findViewById( R.id.other_dysk_fillin ) ;
        novel_beh_txt =  (EditText) findViewById( R.id.novel_behavior_fillin ) ;
        
        String dysk_txt = other_dysk_txt.getText().toString() ;
        String novel_txt = novel_beh_txt.getText().toString() ;
        
        mm.mouse_iteration[mm.cur].other_dysk_text = dysk_txt ;
        mm.mouse_iteration[mm.cur].novel_behavior_text = novel_txt ;
        
        int cur ;
    	for (cur = 0; cur < mm.last_elem; cur++) {
    		ed.putString("state"+cur, mm.mouse_iteration[cur].getState()) ;
    	}
    	
    	ed.putInt("cur", mm.cur) ;
    	//Toast.makeText(getApplicationContext(), "Stopping with cur "+mm.cur, Toast.LENGTH_LONG).show() ;
    	
    	//ed.putBoolean("starting", false) ;
    	ed.commit() ;
    }
    
    public void onClick(View v) {
        TextView time_text = (TextView) findViewById( R.id.timepoint_lbl ) ;
        TextView animal_text = (TextView) findViewById( R.id.animal_lbl ) ;
        TextView bin_text = (TextView) findViewById( R.id.bin_lbl ) ;
        TextView bottom_text = (TextView) findViewById( R.id.label_bottom ) ;
        
        // Regardless of what was pressed, save the text fields to their proper owner
        other_dysk_txt = (EditText) findViewById( R.id.other_dysk_fillin ) ;
        novel_beh_txt =  (EditText) findViewById( R.id.novel_behavior_fillin ) ;
        
        String dysk_txt = other_dysk_txt.getText().toString() ;
        String novel_txt = novel_beh_txt.getText().toString() ;
        
        mm.mouse_iteration[mm.cur].other_dysk_text = dysk_txt ;
        mm.mouse_iteration[mm.cur].novel_behavior_text = novel_txt ;
        
          // shortcut for constants
        MouseIteration mi = mm.mouse_iteration[0] ;
        
        switch(v.getId()) {
            case R.id.start_btn :
            	break;
            case R.id.pause_btn :
            	break;
            case R.id.prev_btn :
            	if (!mm.at_start) {
            		mm.prev_animal() ;
            		MouseIteration mcur = mm.curIteration() ;
                	time_text.setText("Timepoint: "+mcur.timepoint) ;
                	animal_text.setText("Animal: "+mcur.animal) ;
                	bin_text.setText("Bin: "+mcur.bin) ;
                	bottom_text.setText("Cur: "+mm.cur) ;
                	next_btn.setText("Next >") ;
                	reload_button_states() ;
                	if (mm.at_start) {
                		prev_btn.setText("(Prev)") ;
                	}
                	save_restore_file() ;
                	//Toast.makeText(getApplicationContext(), "Current bin "+mcur.bin, Toast.LENGTH_LONG).show() ;
                	
            	}
            	break;
            case R.id.next_btn :
            	if (mm.done || (mm.cur == (mm.num_elems-1))) {
            		
            		boolean mExternalStorageAvailable = false;
            		boolean mExternalStorageWriteable = false;
            		String state = Environment.getExternalStorageState();

            		if (Environment.MEDIA_MOUNTED.equals(state)) {
            		    // We can read and write the media
            		    mExternalStorageAvailable = mExternalStorageWriteable = true;
            		} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            		    // We can only read the media
            		    mExternalStorageAvailable = true;
            		    mExternalStorageWriteable = false;
            		} else {
            		    // Something else is wrong. It may be one of many other states, but all we need
            		    //  to know is we can neither read nor write
            		    mExternalStorageAvailable = mExternalStorageWriteable = false;
            		}
            		
            		if (!mExternalStorageWriteable) {
            			bottom_text.setText("ERROR! NO STORAGE AVAILABLE!") ;
            		} else {
            			save_and_close() ;
            			bottom_text.setText("File saved.") ;
            		}
            	} else {
            		mm.next_animal() ;
            		prev_btn.setText("< Prev") ;
            		MouseIteration mcur = mm.curIteration();
                	time_text.setText("Timepoint: "+mcur.timepoint) ;
                	animal_text.setText("Animal: "+mcur.animal) ;
                	bin_text.setText("Bin: "+mcur.bin) ;
                	bottom_text.setText("Cur: "+mm.cur) ;

                	if (mm.done || (mm.cur == (mm.num_elems-1))) {
                		next_btn.setText("Finish") ;
                	}
                	save_restore_file() ;
                	reload_button_states() ;
            	}
            	Log.i("START", start_notes_txt) ;
            	break;
            case R.id.asleep_btn :
                mm.mouse_iteration[mm.cur].asleep_marked = !mm.mouse_iteration[mm.cur].asleep_marked ;                    
            	break;
            case R.id.awakestill_btn :
                mm.mouse_iteration[mm.cur].inactive_marked = !mm.mouse_iteration[mm.cur].inactive_marked ;
            	break;
            case R.id.loco_int_btn :
            	loco_cont_btn.setChecked(false) ;
            	loco_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].move_level != mi.MOVE_LEVEL_INTERMITTENT) {
            		mm.mouse_iteration[mm.cur].move_level = mi.MOVE_LEVEL_INTERMITTENT ;
            	} else {
            		mm.mouse_iteration[mm.cur].move_level = 0 ;
            	}
            	break;
            case R.id.loco_cont_btn :
            	loco_int_btn.setChecked(false) ;
            	loco_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].move_level != mi.MOVE_LEVEL_CONTINUOUS) {
            		mm.mouse_iteration[mm.cur].move_level = mi.MOVE_LEVEL_CONTINUOUS ;
            	} else {
            		mm.mouse_iteration[mm.cur].move_level = 0 ;
            	}
            	break;
            case R.id.loco_maint_btn :
            	loco_int_btn.setChecked(false) ;
            	loco_cont_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].move_level != mi.MOVE_LEVEL_MAINTAINED) {
            		mm.mouse_iteration[mm.cur].move_level = mi.MOVE_LEVEL_MAINTAINED ;
            	} else {
            		mm.mouse_iteration[mm.cur].move_level = 0 ;
            	}
            	break;
            case R.id.loco_rand_btn :
            	mm.mouse_iteration[mm.cur].exploring = !mm.mouse_iteration[mm.cur].exploring ;
            	break;
            case R.id.loco_patt_btn :
            	mm.mouse_iteration[mm.cur].movement_pattern = ! mm.mouse_iteration[mm.cur].movement_pattern ;
            	break;
            case R.id.piv_once_btn :
            	piv_int_btn.setChecked(false) ;
            	piv_cont_btn.setChecked(false) ;
            	piv_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].pivot_level != mi.PIVOT_LEVEL_ONCE) {
            		mm.mouse_iteration[mm.cur].pivot_level = mi.PIVOT_LEVEL_ONCE ;
            	} else {
            		mm.mouse_iteration[mm.cur].pivot_level = 0 ;
            	}
            	break;
            case R.id.piv_int_btn :
            	piv_once_btn.setChecked(false) ;
            	piv_cont_btn.setChecked(false) ;
            	piv_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].pivot_level != mi.PIVOT_LEVEL_INTERMITTENT) {
            		mm.mouse_iteration[mm.cur].pivot_level = mi.PIVOT_LEVEL_INTERMITTENT ;
            	} else {
            		mm.mouse_iteration[mm.cur].pivot_level = 0 ;
            	}
            	break;
            case R.id.piv_cont_btn :
            	piv_once_btn.setChecked(false) ;
            	piv_int_btn.setChecked(false) ;
            	piv_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].pivot_level != mi.PIVOT_LEVEL_CONTINUOUS) {
            		mm.mouse_iteration[mm.cur].pivot_level = mi.PIVOT_LEVEL_CONTINUOUS ;
            	} else {
            		mm.mouse_iteration[mm.cur].pivot_level = 0 ;
            	}
            	break;
            case R.id.piv_maint_btn :
            	piv_once_btn.setChecked(false) ;
            	piv_int_btn.setChecked(false) ;
            	piv_cont_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].pivot_level != mi.PIVOT_LEVEL_MAINTAINED) {
            		mm.mouse_iteration[mm.cur].pivot_level = mi.PIVOT_LEVEL_MAINTAINED ;
            	} else {
            		mm.mouse_iteration[mm.cur].pivot_level = 0 ;
            	}
            	break;
            case R.id.groom_int_btn :
            	groom_cont_btn.setChecked(false) ;
            	groom_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].groom_level != mi.GROOM_LEVEL_MAINTAINED) {
            		mm.mouse_iteration[mm.cur].groom_level = mi.GROOM_LEVEL_INTERMITTENT ;
            	} else {
            		mm.mouse_iteration[mm.cur].groom_level = 0 ;
            	}
            	break;
            case R.id.groom_cont_btn :
            	groom_int_btn.setChecked(false) ;
            	groom_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].groom_level != mi.GROOM_LEVEL_CONTINUOUS) {
            		mm.mouse_iteration[mm.cur].groom_level = mi.GROOM_LEVEL_CONTINUOUS ;
            	} else {
            		mm.mouse_iteration[mm.cur].groom_level = 0 ;
            	}
            	break;
            case R.id.groom_maint_btn :
            	groom_int_btn.setChecked(false) ;
            	groom_cont_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].groom_level != mi.GROOM_LEVEL_MAINTAINED) {
            		mm.mouse_iteration[mm.cur].groom_level = mi.GROOM_LEVEL_MAINTAINED ;
            	} else {
            		mm.mouse_iteration[mm.cur].groom_level = 0 ;
            	}
            	break;
            case R.id.rear_int_btn :
            	rear_cont_btn.setChecked(false) ;
            	rear_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].rear_level != mi.REAR_LEVEL_INTERMITTENT) {
            		mm.mouse_iteration[mm.cur].rear_level = mi.REAR_LEVEL_INTERMITTENT ;
            	} else {
            		mm.mouse_iteration[mm.cur].rear_level = 0 ;
            	}
            	break;
            case R.id.rear_cont_btn :
            	rear_int_btn.setChecked(false) ;
            	rear_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].rear_level != mi.REAR_LEVEL_CONTINUOUS) {
            		mm.mouse_iteration[mm.cur].rear_level = mi.REAR_LEVEL_CONTINUOUS ;
            	} else {
            		mm.mouse_iteration[mm.cur].rear_level = 0 ;
            	}
            	break;
            case R.id.rear_maint_btn    :
            	rear_int_btn.setChecked(false) ;
            	rear_cont_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].rear_level != mi.REAR_LEVEL_MAINTAINED) {
            		mm.mouse_iteration[mm.cur].rear_level = mi.REAR_LEVEL_MAINTAINED ;
            	} else {
            		mm.mouse_iteration[mm.cur].rear_level = 0 ;
            	}
            	break;
            case R.id.dy_limb_btn : 
            	mm.mouse_iteration[mm.cur].limbs_splayed = !mm.mouse_iteration[mm.cur].limbs_splayed ;
            	break ;
            case R.id.dy_hurt_btn :
            	mm.mouse_iteration[mm.cur].injury = !mm.mouse_iteration[mm.cur].injury ;
            	break ;

            case R.id.sniff_once_btn :
            	sniff_int_btn.setChecked(false) ;
            	sniff_cont_btn.setChecked(false) ;
            	sniff_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].sniff_level != mi.SNIFF_LEVEL_ONCE) {
            		mm.mouse_iteration[mm.cur].sniff_level = mi.SNIFF_LEVEL_ONCE ;
            	} else {
            		mm.mouse_iteration[mm.cur].sniff_level = 0 ;
            	}
            	break;
            case R.id.sniff_int_btn :
            	sniff_once_btn.setChecked(false) ;
            	sniff_cont_btn.setChecked(false) ;
            	sniff_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].sniff_level != mi.SNIFF_LEVEL_INTERMITTENT) {
            		mm.mouse_iteration[mm.cur].sniff_level = mi.SNIFF_LEVEL_INTERMITTENT ;
            	} else {
            		mm.mouse_iteration[mm.cur].sniff_level = 0 ;
            	}
            	break;
            case R.id.sniff_cont_btn :
            	sniff_once_btn.setChecked(false) ;
            	sniff_int_btn.setChecked(false) ;
            	sniff_maint_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].sniff_level != mi.SNIFF_LEVEL_CONTINUOUS) {
            		mm.mouse_iteration[mm.cur].sniff_level = mi.SNIFF_LEVEL_CONTINUOUS ;
            	} else {
            		mm.mouse_iteration[mm.cur].sniff_level = 0 ;
            	}
            	break;
            case R.id.sniff_maint_btn :
            	sniff_once_btn.setChecked(false) ;
            	sniff_int_btn.setChecked(false) ;
            	sniff_cont_btn.setChecked(false) ;
            	if (mm.mouse_iteration[mm.cur].sniff_level != mi.SNIFF_LEVEL_MAINTAINED) {
            		mm.mouse_iteration[mm.cur].sniff_level = mi.SNIFF_LEVEL_MAINTAINED ;
            	} else {
            		mm.mouse_iteration[mm.cur].sniff_level = 0 ;
            	}
            	break;
            case R.id.sniff_hup_btn :
            	mm.mouse_iteration[mm.cur].head_up = !mm.mouse_iteration[mm.cur].head_up ;
            	break;
            case R.id.sniff_hdn_btn :
            	mm.mouse_iteration[mm.cur].head_down = !mm.mouse_iteration[mm.cur].head_down ;
            	break;

            case R.id.sniff_fix_btn :
            	mm.mouse_iteration[mm.cur].head_fixed = !mm.mouse_iteration[mm.cur].head_fixed ;
            	break;
            case R.id.other_head_btn :
            	mm.mouse_iteration[mm.cur].head_bob = !mm.mouse_iteration[mm.cur].head_bob ;
            	break;
            case R.id.other_twitch_btn :
            	mm.mouse_iteration[mm.cur].twitching = !mm.mouse_iteration[mm.cur].twitching;
            	break;
            case R.id.other_bed_btn :
            	mm.mouse_iteration[mm.cur].eating_bedding = !mm.mouse_iteration[mm.cur].eating_bedding ;
            	break;



            case R.id.loco_fast_btn :
            	mm.mouse_iteration[mm.cur].move_fast = !mm.mouse_iteration[mm.cur].move_fast;
            	break;
            case R.id.groom_intense_btn :
            	mm.mouse_iteration[mm.cur].groom_intense = !mm.mouse_iteration[mm.cur].groom_intense;
            	break;
            case R.id.sniff_intense_btn :
            	mm.mouse_iteration[mm.cur].sniff_intense = !mm.mouse_iteration[mm.cur].sniff_intense;
            	break;
            case R.id.dy_seizures_btn :
            	mm.mouse_iteration[mm.cur].seizures = !mm.mouse_iteration[mm.cur].seizures;
            	break;
            case R.id.dy_laying_side_btn :
            	mm.mouse_iteration[mm.cur].laying_on_side = !mm.mouse_iteration[mm.cur].laying_on_side;
            	break;
            case R.id.other_mouthmov_btn :
            	mm.mouse_iteration[mm.cur].mouth_mvmt = !mm.mouse_iteration[mm.cur].mouth_mvmt;
            	break;
            case R.id.other_erect_tail_btn :
            	mm.mouse_iteration[mm.cur].erect_tail = !mm.mouse_iteration[mm.cur].erect_tail;
            	break;
            case R.id.other_flatpos_btn :
            	mm.mouse_iteration[mm.cur].flat_position = !mm.mouse_iteration[mm.cur].flat_position;
            	break ;
            case R.id.other_licking_btn :
            	mm.mouse_iteration[mm.cur].with_licking = !mm.mouse_iteration[mm.cur].with_licking;
            	break ;
        }
    }

    public void reload_button_states() {
          // shortcut for constants
        MouseIteration mi = mm.mouse_iteration[0] ;
      
    	Log.i("reload", "reloading state for button"+mm.cur) ;
    	asleep_btn.setChecked(mm.mouse_iteration[mm.cur].asleep_marked) ;
    	awakestill_btn.setChecked(mm.mouse_iteration[mm.cur].inactive_marked) ;
    	
    	loco_int_btn.setChecked(mm.mouse_iteration[mm.cur].move_level == mi.MOVE_LEVEL_INTERMITTENT) ;
    	loco_cont_btn.setChecked(mm.mouse_iteration[mm.cur].move_level == mi.MOVE_LEVEL_CONTINUOUS) ;
    	loco_maint_btn.setChecked(mm.mouse_iteration[mm.cur].move_level == mi.MOVE_LEVEL_MAINTAINED) ;
    	loco_rand_btn.setChecked(mm.mouse_iteration[mm.cur].exploring) ;
    	loco_patt_btn.setChecked(mm.mouse_iteration[mm.cur].movement_pattern) ;
    	loco_fast_btn.setChecked(mm.mouse_iteration[mm.cur].move_fast) ;
    	
    	piv_once_btn.setChecked(mm.mouse_iteration[mm.cur].pivot_level == mi.PIVOT_LEVEL_ONCE) ;
    	piv_int_btn.setChecked(mm.mouse_iteration[mm.cur].pivot_level == mi.PIVOT_LEVEL_INTERMITTENT) ;
    	piv_cont_btn.setChecked(mm.mouse_iteration[mm.cur].pivot_level == mi.PIVOT_LEVEL_CONTINUOUS) ;
    	piv_maint_btn.setChecked(mm.mouse_iteration[mm.cur].pivot_level == mi.PIVOT_LEVEL_MAINTAINED) ;
    	
    	groom_int_btn.setChecked(mm.mouse_iteration[mm.cur].groom_level == mi.GROOM_LEVEL_INTERMITTENT) ;
    	groom_cont_btn.setChecked(mm.mouse_iteration[mm.cur].groom_level == mi.GROOM_LEVEL_CONTINUOUS) ;
    	groom_maint_btn.setChecked(mm.mouse_iteration[mm.cur].groom_level == mi.GROOM_LEVEL_MAINTAINED) ;
    	groom_intense_btn.setChecked(mm.mouse_iteration[mm.cur].groom_intense) ;
    	
    	rear_int_btn.setChecked(mm.mouse_iteration[mm.cur].rear_level == mi.REAR_LEVEL_INTERMITTENT) ;
    	rear_cont_btn.setChecked(mm.mouse_iteration[mm.cur].rear_level == mi.REAR_LEVEL_CONTINUOUS) ;
    	rear_maint_btn.setChecked(mm.mouse_iteration[mm.cur].rear_level == mi.REAR_LEVEL_MAINTAINED) ;
    	
    	dysk_limb_btn.setChecked(mm.mouse_iteration[mm.cur].limbs_splayed) ;
    	dysk_injury_btn.setChecked(mm.mouse_iteration[mm.cur].injury) ;
    	dysk_seizures_btn.setChecked(mm.mouse_iteration[mm.cur].seizures) ;
    	dysk_laying_side_btn.setChecked(mm.mouse_iteration[mm.cur].laying_on_side) ;

    	sniff_once_btn.setChecked(mm.mouse_iteration[mm.cur].sniff_level == mi.SNIFF_LEVEL_ONCE) ;
    	sniff_int_btn.setChecked(mm.mouse_iteration[mm.cur].sniff_level == mi.SNIFF_LEVEL_INTERMITTENT) ;
    	sniff_cont_btn.setChecked(mm.mouse_iteration[mm.cur].sniff_level == mi.SNIFF_LEVEL_CONTINUOUS) ;
    	sniff_maint_btn.setChecked(mm.mouse_iteration[mm.cur].sniff_level == mi.SNIFF_LEVEL_MAINTAINED) ;
    	sniff_hup_btn.setChecked(mm.mouse_iteration[mm.cur].head_up) ;
    	sniff_hdn_btn.setChecked(mm.mouse_iteration[mm.cur].head_down) ;
    	sniff_fix_btn .setChecked(mm.mouse_iteration[mm.cur].head_fixed);
    	sniff_intense_btn.setChecked(mm.mouse_iteration[mm.cur].sniff_intense) ;
    	
    	other_head_btn.setChecked(mm.mouse_iteration[mm.cur].head_bob) ;
    	other_twitch_btn.setChecked(mm.mouse_iteration[mm.cur].twitching) ;
    	other_bed_btn.setChecked(mm.mouse_iteration[mm.cur].eating_bedding) ;
    	other_flatpos_btn.setChecked(mm.mouse_iteration[mm.cur].flat_position) ;
    	other_licking_btn.setChecked(mm.mouse_iteration[mm.cur].with_licking) ;
    	other_mouth_movement_btn.setChecked(mm.mouse_iteration[mm.cur].mouth_mvmt) ;
    	other_erect_tail_btn.setChecked(mm.mouse_iteration[mm.cur].erect_tail) ;
    	
    	other_dysk_txt.setText(mm.mouse_iteration[mm.cur].other_dysk_text) ;
    	novel_beh_txt.setText(mm.mouse_iteration[mm.cur].novel_behavior_text) ;
    }
    
    public void save_and_close() {
    	
       	String header = "Timepoint, Animal, Bin, Final Result, Asleep, Awake/Inactive, Move Level, " ;
       	header = header + "Exploratory, Patterned, Move Fast, Pivot Level, Groom level, ";
    	header = header + "Intense Grooming, Rear Level, Limbs splayed, Injury, Seizures, " ;
    	header = header + "Laying on Side, Sniff Level, Head up, Head down, Head fixed, " ;
    	header = header + "Intense Sniffing, Head bob, Twitching, Eating bedding, " ;
    	header = header + "Flat Position, Rear With Licking, Mouth Movement, Erect Tail, " ;
    	header = header + "Dyskinesia Notes, Other behaviors" ;
    	    	
    	MouseResult rgen = new MouseResult() ;
    	rgen.set_protocol(protocol) ;
    	mm.finish(rgen) ;
    	
        Time today = new Time(Time.getCurrentTimezone());
        today.setToNow();
        String date = "" + today.year + "_" + (today.month+1) + "_" + today.monthDay ;

    	
        File storage_dir = Environment.getExternalStorageDirectory() ;
        Log.i("WRITEINFO", "Storage dir = " + storage_dir.getAbsolutePath()) ;
    	File dir = new File(storage_dir, File.separator + "MouseMage" + File.separator + date ) ;
    	Log.i("WRITEINFO", "Creating dir " + dir.getAbsolutePath()) ;
    	dir.mkdirs() ;
    	

    	        
    	String file_start = date + "__"
    			+ String.format("%02d",today.hour) + "_"
    			+ String.format("%02d",today.minute) + "_" ;
    	File file = new File(dir, File.separator + file_start + "result.csv");
    	int iterator = 0 ;
    	while (file.exists()) {
    		file = new File(dir, File.separator + file_start + "result" + iterator + ".csv") ;
    		iterator++ ;
    	}
    	
    	Log.i("WRITEINFO", "Writing to file " + file.getAbsolutePath()) ;
    	try {
    		int ptr ;
    		BufferedWriter writer = new BufferedWriter(new FileWriter(file));
    		
    		// Line 1
     		writer.write(start_notes_txt) ;
    		writer.newLine() ;
    		
    		// Line 2 : 2012_3_21,,2:58 PM
    		String hour_str ;
    		String am_pm ;
    		if (today.hour > 12) {
    			hour_str = "" + (today.hour-12) ;
    			am_pm = " PM" ;
    		} else {
    			hour_str = "" + today.hour ;
    			am_pm = " AM" ;
    		}
    		String date_time = date + ",,"
    			+ hour_str + ":"
    			+ String.format("%02d", today.minute) 
    			+ am_pm ;
    		
    		writer.write(date_time) ;
    		writer.newLine() ;
    		
    		// Line 3
    		String my_setup = "Timepoints: " + timepoint
    				+ "  Animals: " + animal
    				+ "  Bins: " + bin
    				+ "  Protocol: " + protocol ;
    		writer.write(my_setup) ;
    		writer.newLine() ;

    		// Line 4
    		writer.write(header) ;
    		writer.newLine() ;
    		
    		// Table
    		for (ptr = 0 ; ptr < mm.mouse_iteration.length ; ptr++) {
    			writer.write(mm.mouse_iteration[ptr].toString());
    			writer.newLine();
    		}
    		writer.flush() ;
    		writer.close() ;
    	} catch (IOException e) {
    		Log.e("WRITERR", "Could not write via BufferedWriter"); 
    	    e.printStackTrace();
    	}

    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	SharedPreferences.Editor ed = settings.edit() ;
        // Handle item selection
        switch (item.getItemId()) {
            case R.id.force_save_menu_item :
                save_and_close();
                return true;
            case R.id.quit :
            	ed.putBoolean("started", false) ;
            	ed.commit() ;
                System.exit(0);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    public String open_restore_file() {
		String FILENAME = "restore_file.dat";
		boolean file_open = false ;
		FileInputStream fis = null;
		String restore_contents = "12080201" ;
		try {

			fis = openFileInput(FILENAME);
			file_open = true ;
		} catch (FileNotFoundException e) {
			Log.i("FNF", "Internal file not found") ;
		}
		if (file_open) {
			try {
				InputStreamReader isr = new InputStreamReader(fis) ;
				BufferedReader br = new BufferedReader(isr) ;
				restore_contents = br.readLine() ;
				fis.close();
				isr.close() ;
				br.close() ;
				Log.i("RF", "Restore file contents") ;
				Log.i("RF", restore_contents) ;
			} catch (IOException ioe) {
				Log.w("IOE", "Error opening backup file") ;
			}
		}
		return (restore_contents) ;	
    }
    public void save_restore_file() {
    	String FILENAME = "restore_file.dat" ;
    	FileOutputStream fos = null ;
    	boolean file_open = false ;
    	String data_stream = toString() ;
    	try {
    		fos = openFileOutput(FILENAME, Context.MODE_PRIVATE) ;
    		file_open = true ;
    	} catch (FileNotFoundException fnf) {
    		Log.w("FNF", "Internal file not found") ;
    	}
    	if (file_open) {
    		try {
    			fos.write(data_stream.getBytes()) ;
    			fos.close() ;
    		} catch (IOException ioe) {
    			Log.w("IOE", "Error writing to backup file") ;
    		}    		
    	}
    }
    public String toString() {
    	String sep1 = "//!" ;
    	String sep2 = "//@" ;
    	String dump = "" + timepoint
    			+ sep1 + animal
    			+ sep1 + bin
    			+ sep1 + protocol
    			+ sep1 + mm.cur
    			+ sep2 + (mm.done? "1" : "0")
    			+ sep2 + "@" + start_notes_txt ;
    	int cur_mm = 0 ;
    	for (cur_mm = 0 ; cur_mm <= mm.last_elem; cur_mm++) {
    		dump += sep2 + mm.mouse_iteration[cur_mm].getState() ;
    	}
    	
    	Log.i("ToS", "Dumping temp file with contents:") ;
    	Log.i("ToS", dump) ;
    	
    	return (dump) ;
    }
}